home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 376-400 / disk_386 / xlispstat / src2.lzh / XLisp-Stat / xshistogram.c < prev    next >
C/C++ Source or Header  |  1990-10-09  |  24KB  |  868 lines

  1. /* xshistogram - XLISP interface to IVIEW dynamic graphics package.    */
  2. /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney                  */
  3. /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz    */
  4. /* You may give out copies of this software; for conditions see the    */
  5. /* file COPYING included with this distribution.                       */
  6.  
  7. #include <string.h>
  8. #include "xlisp.h"
  9. #include "osdef.h"
  10. #ifdef ANSI
  11. #include "xlproto.h"
  12. #include "xlsproto.h"
  13. #include "iviewproto.h"
  14. #include "Stproto.h"
  15. #else
  16. #include "xlfun.h"
  17. #include "xlsfun.h"
  18. #include "iviewfun.h"
  19. #include "Stfun.h"
  20. #endif ANSI
  21. #include "xlsvar.h"
  22.  
  23. #define HIST_MAX_BINS 50
  24. #define HIST_INITIAL_BINS 6
  25. #define NOT_IN_HIST -2
  26. #define NO_MORE_POINTS -1
  27. #define BIN_POINTER -1
  28. #define HIST_CLICK_WIDTH 1
  29. #define HIST_CLICK_HEIGHT 1
  30.  
  31. typedef struct hist_point {
  32.   int left, top, width, height, next;
  33. } HistPoint;
  34.  
  35. typedef struct hist_bin {
  36.   int low, high, count, height, smallest;
  37. } Bin;
  38.  
  39. typedef struct hist {
  40.   Bin bins[HIST_MAX_BINS];
  41.   char *point_data;
  42.   int num_bins, num_showing;
  43. } *IViewHist;
  44.  
  45. /* forward declarations */
  46. #ifdef ANSI
  47. LVAL gethistdata(LVAL);
  48. IViewHist getinternals(LVAL);
  49. HistPoint *getpointdata(LVAL);
  50. void bad_hist_data(void),IViewHistSetNumBins(LVAL,LVAL,int),clear_bins(LVAL),
  51.      size_bins(IVIEW_WINDOW,LVAL),draw_hist(IVIEW_WINDOW,LVAL),
  52.      initialize_points(IVIEW_WINDOW,LVAL,int,int),
  53.      find_point_rects(IVIEW_WINDOW,LVAL),hilite_points(IVIEW_WINDOW,LVAL),
  54.      draw_hist_point_state(IVIEW_WINDOW,LVAL,int,PointState),
  55.      set_density_range(IVIEW_WINDOW,int,double),
  56.      gethistargs(IVIEW_WINDOW *,LVAL *,LVAL *),
  57.      allocate_internal_points(LVAL,int),clear_internal_points(LVAL),
  58.      clear_internal_points(LVAL),IViewHistResize(IVIEW_WINDOW,LVAL),
  59.      IViewHistRedrawContent(IVIEW_WINDOW,LVAL);
  60. int sort_bins(IVIEW_WINDOW,LVAL),sect_point_rect(LVAL,int,int,int,int,int),
  61.     remove_non_showing_points(IVIEW_WINDOW,LVAL),
  62.     insert_point(IVIEW_WINDOW,LVAL,int,int,int),IViewHistNumBins(LVAL);
  63. #else
  64. LVAL gethistdata();
  65. IViewHist getinternals();
  66. HistPoint *getpointdata();
  67. void bad_hist_data(),IViewHistSetNumBins(),clear_bins(),
  68.      size_bins(),draw_hist(),
  69.      initialize_points(),
  70.      find_point_rects(),hilite_points(),
  71.      draw_hist_point_state(),
  72.      set_density_range(),
  73.      gethistargs(),
  74.      allocate_internal_points(),clear_internal_points(),
  75.      clear_internal_points(),IViewHistResize(),
  76.      IViewHistRedrawContent();
  77. int sort_bins(),sect_point_rect(),
  78.     remove_non_showing_points(),
  79.     insert_point(),IViewHistNumBins();
  80. #endif ANSI
  81.  
  82. static LVAL gethistdata(object)
  83.     LVAL object;
  84. {
  85.   LVAL val;
  86.   
  87.   val = slot_value(object, s_histogram_internals);
  88.   if (! consp(val) || !adatap(car(val))) bad_hist_data();
  89.   else return(val);
  90. }
  91.  
  92. static HistPoint *getpointdata(hdata)
  93.     LVAL hdata;
  94. {
  95.   if (adatap(cdr(hdata)))     /* cast added JKL */
  96.     return((HistPoint *) StRPtr((StReallocData)getadaddr(cdr(hdata))));
  97.   else return(nil);
  98. }
  99.   
  100. static IViewHist getinternals(hdata)
  101.     LVAL hdata;
  102. {
  103.   if (getadaddr(car(hdata)) == nil) bad_hist_data();
  104.   else return((IViewHist) getadaddr(car(hdata)));
  105. }
  106.  
  107. static void gethistargs(w, object, hdata)
  108.     IVIEW_WINDOW *w;
  109.     LVAL *object, *hdata;
  110. {
  111.   *object = xlgaobject();
  112.   if (w != nil) *w = GETIVIEWADDRESS(*object);
  113.   if (hdata != nil) *hdata = gethistdata(*object);
  114. }
  115.  
  116. void newhistinternals(object)
  117.     LVAL object;
  118. {
  119.   LVAL val;
  120.   
  121.   xlsave1(val);
  122.   val = newadata(sizeof(struct hist), 1, FALSE);
  123.   val = consa(val);
  124.   set_slot_value(object, s_histogram_internals, val);
  125.   xlpop();
  126. }
  127.  
  128. static void allocate_internal_points(object, n)
  129.     LVAL object;
  130.     int n;
  131. {
  132.   LVAL val;
  133.   val = gethistdata(object);
  134.   if (adatap(cdr(val)))
  135.     reallocaddata(cdr(val), sizeof(struct hist_point), n);
  136.   else
  137.     rplacd(val, newadata(sizeof(struct hist_point), n, TRUE));
  138. }  
  139.  
  140. static void clear_internal_points(object)
  141.     LVAL object;
  142. {
  143.   LVAL val;
  144.   
  145.   val = slot_value(object, s_histogram_internals);
  146.   if (! consp(val) || ! adatap(cdr(val))) bad_hist_data();
  147.   freeadata(cdr(val));
  148. }
  149.  
  150. static void bad_hist_data() { xlfail("bad internal histogram data"); }
  151.  
  152. /**************************************************************************/
  153. /**                                                                      **/
  154. /**                     Histogram Creation Functions                     **/
  155. /**                                                                      **/
  156. /**************************************************************************/
  157.  
  158. LVAL iview_hist_isnew()
  159. {
  160.   LVAL object, args, hdata;
  161.   int vars;
  162.   
  163.   object = xlgaobject();
  164.   vars = getfixnum(xlgafixnum());
  165.   if (vars < 1) xlfail("bad number of variables for histogram");
  166.   
  167.   newhistinternals(object);
  168.   hdata = gethistdata(object);
  169.   IViewHistSetNumBins(object, hdata, HIST_INITIAL_BINS);
  170.   clear_bins(hdata);
  171.  
  172.   xlsave1(args);
  173.   args = makearglist(xlargc, xlargv);
  174.   args = cons(cvfixnum((FIXTYPE) (vars + 1)), args);
  175.   args = cons(object, args);
  176.   xsapplysubr(iview_isnew, args);
  177.   xlpop();
  178.  
  179.   return(object);
  180. }
  181.  
  182. LVAL iview_hist_allocate()
  183.  
  184. {
  185.   LVAL object;
  186.   IVIEW_WINDOW w;
  187.   int vars, show;
  188.   /*char*/ StGWWinInfo *gwinfo;/* changed JKL */
  189.  
  190.   object = xlgaobject();
  191.   show = xsboolkey(sk_show, TRUE);
  192.   
  193.   gwinfo = StGWObWinInfo(object);
  194.   w = IViewNew(object);
  195.   initialize_iview(w, object);
  196.  
  197.   vars = IViewNumVariables(w);
  198.   StGrSetClickRange(gwinfo, HIST_CLICK_WIDTH, HIST_CLICK_HEIGHT);
  199.   StGrSetContentVariables(gwinfo, 0, vars - 1);
  200.  
  201.   /* use StShowWindow to show (map) window but NOT send :resize or :redraw */
  202.   if (show) StShowWindow(w);
  203.   
  204.   return(object);
  205. }
  206.  
  207. /**************************************************************************/
  208. /**                                                                      **/
  209. /**                     State Accessors and Mutators                     **/
  210. /**                                                                      **/
  211. /**************************************************************************/
  212.  
  213. static void IViewHistSetNumBins(object, hdata, n)
  214.     LVAL object, hdata;
  215.     int n;
  216. {
  217.   IViewHist h = getinternals(hdata);
  218.   
  219.   if (n < 1 || n > HIST_MAX_BINS) return;
  220.   h->num_bins = n;
  221.   send_message(object, sk_resize);
  222. }
  223.  
  224. static int IViewHistNumBins(hdata)
  225.     LVAL hdata;
  226. {
  227.   IViewHist h = getinternals(hdata);
  228.   
  229.   return(h->num_bins);
  230. }
  231.   
  232. LVAL iview_hist_num_bins()
  233. {
  234.   LVAL object, hdata;
  235.   IVIEW_WINDOW w;
  236.   int bins;
  237.   
  238.   gethistargs(&w, &object, &hdata);
  239.   if (moreargs()) {
  240.     bins = getfixnum(xlgafixnum());
  241.     IViewHistSetNumBins(object, hdata, bins);
  242.     check_redraw(object, TRUE, TRUE);
  243.   }
  244.   return(cvfixnum((FIXTYPE) IViewHistNumBins(hdata)));
  245. }
  246.  
  247. LVAL iview_hist_bin_counts()
  248. {
  249.   LVAL object, hdata, result, next;
  250.   IVIEW_WINDOW w;
  251.   int i, bins;
  252.   IViewHist h;
  253.   
  254.   gethistargs(&w, &object, &hdata);
  255.   xllastarg();
  256.   
  257.   if (hdata == nil || (h = getinternals(hdata)) == nil) result = NIL;
  258.   else {
  259.     bins = h->num_bins;
  260.     xlsave1(result);
  261.     result = mklist(bins, NIL);
  262.     for (i = 0, next = result; i < bins; i++, next = cdr(next))
  263.       rplaca(next, cvfixnum((FIXTYPE) h->bins[i].count));
  264.     xlpop();
  265.   }
  266.   return(result);
  267. }
  268.  
  269. /**************************************************************************/
  270. /**                                                                      **/
  271. /**                            Data Functions                            **/
  272. /**                                                                      **/
  273. /**************************************************************************/
  274.  
  275. LVAL iview_hist_add_points()
  276. {
  277.   IVIEW_WINDOW w;
  278.   int old_n, n;
  279.   LVAL object, data, hdata;
  280.   
  281.   gethistargs(&w, &object, &hdata);
  282.   if (w == nil) return(NIL);
  283.   
  284.   old_n = IViewNumPoints(w);
  285.   
  286.   xlsave1(data);
  287.   data = xlgetarg();
  288.   data = (fixp(data) || (consp(data) && sequencep(car(data)))) 
  289.        ? data : consa(data);
  290.   internal_iview_add_points(w, object, data);
  291.   xlpop();
  292.   
  293.   n = IViewNumPoints(w);
  294.   allocate_internal_points(object, n);
  295.   initialize_points(w, hdata, old_n, n);
  296.   
  297.   check_add_to_screen(object, 'P', old_n, n, TRUE);
  298.   
  299.   return(NIL);
  300. }
  301.  
  302. LVAL iview_hist_clear_points()
  303. {
  304.   IVIEW_WINDOW w;
  305.   LVAL object, hdata;
  306.   
  307.   gethistargs(&w, &object, &hdata);
  308.  
  309.   if (w != nil) {
  310.     IViewClearPoints(w);
  311.     clear_bins(hdata);
  312.     clear_internal_points(object);
  313.     check_redraw(object, TRUE, TRUE);
  314.   }
  315.   return(NIL);
  316. }
  317.  
  318. /**************************************************************************/
  319. /**                                                                      **/
  320. /**                    Drawing and Resizing Functions                    **/
  321. /**                                                                      **/
  322. /**************************************************************************/
  323.  
  324. static void IViewHistResize(w, hdata)
  325.      IVIEW_WINDOW w;
  326.      LVAL hdata;
  327. {
  328.   IViewStdResize(w);
  329.   clear_bins(hdata);
  330.   initialize_points(w, hdata, 0, IViewNumPoints(w));
  331. }
  332.  
  333. static void IViewHistRedrawContent(w, hdata)
  334.     IVIEW_WINDOW w;
  335.     LVAL hdata;
  336. {
  337.   int left, top, width, height, x, y, vleft, vtop, vwidth, vheight;
  338.   /*char*/ StGWWinInfo *gwinfo; /* changed JKL */
  339.   
  340.   gwinfo = IViewWindowWinInfo(w);
  341.  
  342.   if (IViewMouseMode(w) == brushing) IViewEraseBrush(w);
  343.   IViewGetContentMarginRect(w, &left, &top, &width, &height);
  344.   StGrGetContentVariables(gwinfo, &x, &y);
  345.   
  346.   StGWStartBuffering(gwinfo);
  347.   StGWSetClipRect(gwinfo, TRUE, left, top, width + 1, height + 1);
  348.   StGWEraseRect(gwinfo, left, top, width + 1, height + 1);
  349.  
  350.   sort_bins(w, hdata);
  351.   size_bins(w, hdata);
  352.   draw_hist(w, hdata);
  353.   IViewDrawDataLines(w, x, y, 0, IViewNumLines(w));
  354. #ifdef USESTRINGS
  355.   IViewDrawDataStrings(w, x, y, 0, IViewNumStrings(w));
  356. #endif /* USESTRINGS */
  357.   StGWBufferToScreen(gwinfo, left, top, width + 1, height + 1);
  358.   StGWGetViewRect(gwinfo, &vleft, &vtop, &vwidth, &vheight);
  359.   StGWSetClipRect(gwinfo, TRUE, vleft, vtop, vwidth, vheight);
  360.   if (IViewMouseMode(w) == brushing) IViewDrawBrush(w);
  361.   IViewResetScreenStates(w);
  362. }
  363.  
  364. LVAL iview_hist_resize()
  365. {
  366.   LVAL object, hdata;
  367.   IVIEW_WINDOW w;
  368.  
  369.   gethistargs(&w, &object, &hdata);
  370.   if (w != nil) IViewHistResize(w, hdata);
  371.   return(NIL);
  372. }
  373.  
  374. LVAL iview_hist_redraw_content()
  375. {
  376.   LVAL object, hdata;
  377.   IVIEW_WINDOW w;
  378.  
  379.   gethistargs(&w, &object, &hdata);
  380.   if (w != nil) IViewHistRedrawContent(w, hdata);
  381.   return(NIL);
  382. }
  383.  
  384. LVAL iview_hist_adjust_to_data()
  385. {
  386.   LVAL object;
  387.   IVIEW_WINDOW w;
  388.   /*char*/ StGWWinInfo *gwinfo; /* changed JKL */
  389.   double low, high;
  390.   int ticks, labeled, x, y, scaled, bins;
  391.   char *label;
  392.   LVAL arg, hdata;
  393.   
  394.   gethistargs(&w, &object, &hdata);
  395.  
  396.   if (w != nil) {
  397.     gwinfo = StGWObWinInfo(object);
  398.     StGrObAdjustToData(object, FALSE);
  399.     scaled = (slot_value(object, s_scale_type) != NIL) ? TRUE : FALSE;
  400.     
  401.     StGrGetContentVariables(gwinfo, &x, &y);
  402.     IViewGetRange(w, x, &low, &high);
  403.     label = IViewVariableLabel(w, x);
  404.     labeled = (label != nil && strlen(label) > 0) ? TRUE : FALSE;
  405.     ticks = 4;
  406.     GetNiceRange(&low, &high, &ticks);
  407.     IViewSetRange(w, x, low, high);
  408.     IViewSetXaxis(w, ! scaled, labeled, ticks);
  409.     bins = 5 + log(1.0 + IViewNumPoints(w));
  410.     GetNiceRange(&low, &high, &bins);
  411.     if (bins > 1) bins --;
  412.     if (bins > 30) bins = 30;
  413.     IViewHistSetNumBins(object, hdata, bins);
  414.  
  415.     if (! xlgetkeyarg(sk_draw, &arg)) arg = s_true;
  416.     if (arg != NIL) send_message(object, sk_resize);
  417.     if (arg != NIL) send_message(object, sk_redraw);  
  418.   }
  419.   return(NIL);
  420. }
  421.  
  422. /**************************************************************************/
  423. /**                                                                      **/
  424. /**                           Mouse Functions                            **/
  425. /**                                                                      **/
  426. /**************************************************************************/
  427.  
  428. LVAL iview_hist_adjust_screen()
  429. {
  430.   IVIEW_WINDOW w;
  431.   LVAL object, hdata;
  432.   int x, y, lines_only = FALSE;
  433.   /*char*/ StGWWinInfo *gwinfo; /* changed JKL */
  434.  
  435.   gethistargs(&w, &object, &hdata);
  436.  
  437.   if (w == nil) return(NIL);
  438.   gwinfo = StGWObWinInfo(object);
  439.   if (StGrDirty(gwinfo)) {
  440.     StGrSetDirty(gwinfo, FALSE);
  441.     if (lines_only) {
  442.       if (IViewMouseMode(w) == brushing) IViewEraseBrush(w);
  443.       StGrGetContentVariables(gwinfo, &x, &y);
  444.       IViewDrawDataLines(w, x, y, 0, IViewNumLines(w));
  445. #ifdef USESTRINGS
  446.       IViewDrawDataStrings(w, x, y, 0, IViewNumStrings(w));
  447. #endif /* USESTRINGS */
  448.       if (IViewMouseMode(w) == brushing) IViewDrawBrush(w);
  449.     }
  450.     else {
  451.       IViewHistResize(w, hdata);
  452.       IViewHistRedrawContent(w, hdata);
  453.     }
  454.   }
  455.   return(NIL);
  456. }
  457.  
  458. LVAL iview_hist_adjust_points_in_rect()
  459. {
  460.   int  i, n, in_rect;
  461.   PointState point_state;
  462.   IVIEW_WINDOW w;
  463.   int left, top, width, height;
  464.   PointState state;
  465.   LVAL object, hdata;
  466.   
  467.   gethistargs(&w, &object, &hdata);
  468.  
  469.   left = getfixnum(xlgafixnum());
  470.   top = getfixnum(xlgafixnum());
  471.   width = getfixnum(xlgafixnum());
  472.   height = getfixnum(xlgafixnum());
  473.   state = decode_point_state(xlgetarg());
  474.  
  475.   if (w == nil) return(NIL);
  476.   
  477.   IViewCheckLinks(w);
  478.   n = IViewNumPoints(w);
  479.   if (IViewMouseMode(w) == brushing) IViewEraseBrush(w);
  480.  
  481.   for (i = 0; i < n; i++) {
  482.     point_state = IViewPointState(w, i);
  483.     if (! IViewPointMasked(w, i) && point_state != pointInvisible) {
  484.       in_rect = sect_point_rect(hdata, i, left, top, width, height);
  485.       if (in_rect && (int) point_state < (int) state) {
  486.         IViewSetPointState(w, i, state);
  487.       }
  488.       else if (! in_rect
  489.            && state == pointHilited
  490.            && point_state == pointHilited) {
  491.         IViewSetPointState(w, i, pointNormal);
  492.       }
  493.     }
  494.   }
  495.   IViewAdjustScreens(w);
  496.   if (IViewMouseMode(w) == brushing) IViewDrawBrush(w);
  497.   return(NIL);
  498. }
  499.  
  500. LVAL iview_hist_mark_points_in_rect()
  501. {
  502.   int  i, n, in_rect;
  503.   PointState point_state;
  504.   IVIEW_WINDOW w;
  505.   int left, top, width, height;
  506.   LVAL object, hdata;
  507.   
  508.   gethistargs(&w, &object, &hdata);
  509.  
  510.   left = getfixnum(xlgafixnum());
  511.   top = getfixnum(xlgafixnum());
  512.   width = getfixnum(xlgafixnum());
  513.   height = getfixnum(xlgafixnum());
  514.  
  515.   if (w == nil) return(NIL);
  516.   
  517.   n = IViewNumPoints(w);
  518.  
  519.   for (i = 0; i < n; i++) {
  520.     point_state = IViewPointState(w, i);
  521.     if (! IViewPointMasked(w, i) && point_state != pointInvisible) {
  522.       in_rect = sect_point_rect(hdata, i, left, top, width, height);
  523.       IViewSetPointMark(w, i, in_rect);
  524.     }
  525.   }
  526.   return(NIL);
  527. }
  528.  
  529. LVAL iview_hist_adjust_screen_point()
  530. {
  531.   IVIEW_WINDOW w;
  532.   LVAL object, hdata;
  533.   int point;
  534.   PointState state, screen_state;
  535.   
  536.   gethistargs(&w, &object, &hdata);
  537.   point = getfixnum(xlgafixnum());
  538.   
  539.   if (w != nil && ! IViewPointMasked(w, point)) {
  540.     state = IViewPointState(w, point);
  541.     screen_state = IViewPointScreenState(w, point);
  542.     if (state == pointInvisible || screen_state == pointInvisible) {
  543.       StGrSetDirty(StGWObWinInfo(object), TRUE);
  544.     }
  545.     else {
  546.       draw_hist_point_state(w, hdata, point, state);
  547.     }
  548.   }    
  549.   return(NIL);
  550. }
  551.  
  552. /**************************************************************************/
  553. /**                                                                      **/
  554. /**                         Internal Functions                           **/
  555. /**                                                                      **/
  556. /**************************************************************************/
  557.  
  558. static void clear_bins(hdata)
  559.     LVAL hdata;
  560. {
  561.   IViewHist h = getinternals(hdata);
  562.   int i;
  563.    
  564.   for (i = 0; i < h->num_bins; i++) {
  565.     h->bins[i].low = 0;
  566.     h->bins[i].high = 0;
  567.     h->bins[i].count = 0;
  568.     h->bins[i].height = 0;
  569.     h->bins[i].smallest = NO_MORE_POINTS;
  570.   }
  571. }
  572.   
  573. static sort_bins(w, hdata)
  574.     IVIEW_WINDOW w;
  575.     LVAL hdata;
  576. {
  577.   IViewHist h = getinternals(hdata);
  578.   int i, k, low, high, val, x, y, n = IViewNumPoints(w);
  579.   int changed = FALSE;
  580.   /*char*/ StGWWinInfo *gwinfo; /* not used JKL */
  581.   
  582.   gwinfo = IViewWindowWinInfo(w);
  583.  
  584.   StGrGetContentVariables(gwinfo, &x, &y);
  585.   IViewGetScreenRange(w, x, &low, &high);
  586.   if (high <= low) return(FALSE);
  587.   if (remove_non_showing_points(w, hdata)) changed = TRUE;
  588.   for (i = 0; i < h->num_bins; i++) h->bins[i].count = 0;
  589.   h->num_showing = 0;
  590.   for (i = 0; i < n; i++) {
  591.     if (! IViewPointMasked(w, i) && IViewPointState(w, i) != pointInvisible) {
  592.       val = IViewPointScreenValue(w, x, i);
  593.       k = (h->num_bins * (val - low)) / (high - low);
  594.       if (k == h->num_bins && val == high) k--; /* on boundary of last bin */
  595.       if (k >= 0 && k < h->num_bins) {
  596.         h->bins[k].count++;
  597.         if (insert_point(w, hdata, x, i, k)) changed = TRUE;
  598.         h->num_showing++;
  599.       }
  600.     }
  601.   }
  602.   return(changed);
  603. }
  604.  
  605. static void size_bins(w, hdata)
  606.     IVIEW_WINDOW w;
  607.     LVAL hdata;
  608. {
  609.   IViewHist h = getinternals(hdata);
  610.   int i, low, high, width, x, y, maxcount, m;
  611.   double factor, density, x_low, x_high, range;
  612.   /*char*/ StGWWinInfo *gwinfo = IViewWindowWinInfo(w); /* changed JKL */
  613.  
  614.   StGrGetContentVariables(gwinfo, &x, &y);
  615.   StGrGetContentRect(gwinfo, &low, nil, &width, nil);
  616.   high = low + width;
  617.   
  618.   maxcount = 1;
  619.   for (i = 0; i < h->num_bins; i++) {
  620.     h->bins[i].low = low + (i * (high - low)) / h->num_bins;
  621.     h->bins[i].high = low + ((i + 1) * (high - low)) / h->num_bins;
  622.     maxcount = (h->bins[i].count > maxcount) ? h->bins[i].count : maxcount;
  623.   }
  624.   
  625.   IViewGetScreenRange(w, y, &low, &high);
  626.   IViewGetScaledRange(w, x, &x_low, &x_high);
  627.   range = x_high - x_low;
  628.   m = h->num_showing;
  629.   density = (range > 0.0 && m > 0) ? 1.2 * (h->num_bins * maxcount / range) / m : 1.0;
  630.   set_density_range(w, y, density);
  631.   factor = ((double) (high - low)) / (maxcount * 1.2);
  632.   for (i = 0; i < h->num_bins; i++) {
  633.     h->bins[i].height = h->bins[i].count * factor;
  634.   }
  635.   find_point_rects(w, hdata);
  636. }
  637.  
  638. static void draw_hist(w, hdata)
  639.     IVIEW_WINDOW w;
  640.     LVAL hdata;
  641. {
  642.   IViewHist h = getinternals(hdata);
  643.   int i, left, top, width, height, content_top, content_height;
  644.   /*char*/ StGWWinInfo *gwinfo = IViewWindowWinInfo(w); /* changed JKL */
  645.    
  646.   StGrGetContentRect(gwinfo, nil, &content_top, nil, &content_height);
  647.   
  648.   for (i = 0; i < h->num_bins; i++) {
  649.     left = h->bins[i].low;
  650.     top  = content_top  + content_height - h->bins[i].height;
  651.     width = h->bins[i].high - left + 1;
  652.     height = h->bins[i].height + 1;
  653.     StGWFrameRect(gwinfo, left, top, width, height);
  654.   }
  655.   hilite_points(w, hdata);
  656. }
  657.  
  658. static void initialize_points(w, hdata, m, n)
  659.     IVIEW_WINDOW w;
  660.     LVAL hdata;
  661.     int m, n;
  662. {
  663.   HistPoint *points;
  664.   int i;
  665.    
  666.   if (m < 0 || n > IViewNumPoints(w)) return;
  667.   points = getpointdata(hdata);
  668.   for (i = m; i < n; i++) {
  669.     points[i].left = 0;
  670.     points[i].top = 0;
  671.     points[i].width = 0;
  672.     points[i].height = 0;
  673.     points[i].next = NOT_IN_HIST;
  674.   }
  675. }
  676.  
  677. static int insert_point(w, hdata, var, p, bin)
  678.     IVIEW_WINDOW w;
  679.     LVAL hdata;
  680.     int var, p, bin;
  681. {
  682.   IViewHist h = getinternals(hdata);
  683.   int last, current, bin_value, point_value;
  684.   HistPoint* points;
  685.    
  686.   points = getpointdata(hdata);
  687.  
  688.   if (points[p].next != NOT_IN_HIST) return(FALSE); /* already in hist */
  689.   
  690.   point_value = IViewPointScreenValue(w, var, p);
  691.   last = BIN_POINTER;
  692.   current = h->bins[bin].smallest;
  693.   bin_value = (current >= 0) ? IViewPointScreenValue(w, var, current) : 0;
  694.   while (bin_value < point_value && current != NO_MORE_POINTS) {
  695.     last = current;
  696.     current = points[current].next;
  697.     bin_value = (current >= 0) ? IViewPointScreenValue(w, var, current) : 0;
  698.   }
  699.   
  700.   points[p].next = current;
  701.   if (last == BIN_POINTER) h->bins[bin].smallest = p;
  702.   else points[last].next = p;
  703.   
  704.   return(TRUE);
  705. }
  706.  
  707. static int remove_non_showing_points(w, hdata)
  708.     IVIEW_WINDOW w;
  709.     LVAL hdata;
  710. {
  711.   IViewHist h = getinternals(hdata);
  712.   int last, next, showing, p, bin;
  713.   HistPoint* points;
  714.   int changed = FALSE;
  715.   
  716.   points = getpointdata(hdata);
  717.  
  718.   for (bin = 0; bin < h->num_bins; bin++) 
  719.     for (p = h->bins[bin].smallest, last = BIN_POINTER; p >= 0;) {  
  720.       showing = (! IViewPointMasked(w, p) && IViewPointState(w, p) != pointInvisible);
  721.       if (showing) {
  722.         last = p;
  723.         p = points[p].next;
  724.       }
  725.       else {
  726.         changed = TRUE;
  727.         if (last == BIN_POINTER) h->bins[bin].smallest = points[p].next;
  728.         else points[last].next = points[p].next;
  729.         next = points[p].next;
  730.         points[p].next = NOT_IN_HIST;
  731.         p = next;
  732.       }
  733.     }
  734.   return(changed);
  735. }
  736.  
  737. static void find_point_rects(w, hdata)
  738.     IVIEW_WINDOW w;
  739.     LVAL hdata;
  740. {
  741.   IViewHist h = getinternals(hdata);
  742.   int showing, p, k, bin, bin_width, bin_left, height, bottom, top, count, base;
  743.   HistPoint* points;
  744.   /*char*/ StGWWinInfo *gwinfo; /* changed JKL */
  745.   
  746.   gwinfo = IViewWindowWinInfo(w);
  747.   points = getpointdata(hdata);
  748.  
  749.   StGrGetContentOrigin(gwinfo, nil, &base);
  750.   
  751.   for (bin = 0; bin < h->num_bins; bin++) {
  752.     bin_left = h->bins[bin].low + 1;
  753.     bin_width = h->bins[bin].high - h->bins[bin].low - 1;
  754.     count = h->bins[bin].count;
  755.     height = h->bins[bin].height - 1;
  756.     for (p = h->bins[bin].smallest, k = 0; p >= 0; p = points[p].next) {  
  757.       showing = (! IViewPointMasked(w, p) && IViewPointState(w, p) != pointInvisible);
  758.       if (showing) {
  759.         points[p].left = bin_left;
  760.         points[p].width = bin_width;
  761.         bottom = base - ((count > 0) ? (height * k) / count : 0);
  762.         top = base - ((count > 0) ? (height * (k + 1)) / count : 0);
  763.         points[p].top = top;
  764.         points[p].height = bottom - top;
  765.         k++;
  766.       }
  767.     }
  768.   }
  769. }
  770.  
  771. static void hilite_points(w, hdata)
  772.     IVIEW_WINDOW w;
  773.     LVAL hdata;
  774. {
  775.   int p, n = IViewNumPoints(w);
  776.   HistPoint* points;
  777.   /*int*/ ColorCode oldcolor, color, use_color; /* changed JKL */
  778.   /*char*/ StGWWinInfo *gwinfo;
  779.  
  780.   gwinfo = IViewWindowWinInfo(w);
  781.   
  782.   points = getpointdata(hdata);
  783.   if (points == nil) return;
  784.   use_color = StGWUseColor(gwinfo);
  785.   
  786.   for (p = 0; p < n; p++)
  787.     if (points[p].next != NOT_IN_HIST && IViewPointState(w, p) != pointNormal) {
  788.       if (use_color) {
  789.         oldcolor = StGWDrawColor(gwinfo);
  790.         color = IViewPointColor(w, p);
  791.         if (color >= 0) StGWSetDrawColor(gwinfo, color);
  792.       }
  793.       StGWPaintRect(gwinfo, points[p].left, points[p].top,
  794.                             points[p].width, points[p].height);
  795.       if (use_color && color >= 0) StGWSetDrawColor(gwinfo, oldcolor);
  796.     }
  797. }
  798.  
  799. static int sect_point_rect(hdata, p, left, top, width, height)
  800.     LVAL hdata;
  801.     int p, left, top, width, height;
  802. {
  803.   int right, bottom, p_right, p_bottom;
  804.   HistPoint* points;
  805.   
  806.   points = getpointdata(hdata);
  807.  
  808.   right = left + width;
  809.   bottom = top + height;
  810.   p_right = points[p].left + points[p].width;
  811.   p_bottom = points[p].top + points[p].height;
  812.   
  813.   left = (left > points[p].left) ? left : points[p].left;
  814.   top = (top > points[p].top) ? top : points[p].top;
  815.   right = (right < p_right) ? right : p_right;
  816.   bottom = (bottom < p_bottom) ? bottom : p_bottom;
  817.   
  818.   return((left <= right) && (top <= bottom));
  819. }
  820.  
  821. static void draw_hist_point_state(w, hdata, p, state)
  822.     IVIEW_WINDOW w;
  823.     LVAL hdata;
  824.     int p;
  825.     PointState state;
  826. {
  827.   HistPoint* points;
  828.   /*int*/ ColorCode oldcolor, color, use_color; /* changed JKL */
  829.   /*char*/ StGWWinInfo *gwinfo;
  830.  
  831.   gwinfo = IViewWindowWinInfo(w);
  832.   
  833.   points = getpointdata(hdata);
  834.  
  835.   if (state == pointNormal)
  836.     StGWEraseRect(gwinfo, points[p].left, points[p].top,
  837.                           points[p].width, points[p].height);
  838.   else {
  839.     use_color = StGWUseColor(gwinfo);
  840.     if (use_color) {
  841.       oldcolor = StGWDrawColor(gwinfo);
  842.       color = IViewPointColor(w, p);
  843.       if (color >= 0) StGWSetDrawColor(gwinfo, color);
  844.     }
  845.     StGWPaintRect(gwinfo, points[p].left, points[p].top,
  846.                           points[p].width, points[p].height);
  847.     if (use_color && color >= 0) StGWSetDrawColor(gwinfo, oldcolor);
  848.   }
  849.   IViewSetPointScreenState(w, p, state);
  850. }
  851.  
  852.  
  853. static void set_density_range(w, y, density)
  854.     IVIEW_WINDOW w;
  855.     int y;
  856.     double density;
  857. {
  858.   int showing, labeled, ticks;
  859.   double low = 0.0;
  860.   
  861.   IViewGetYaxis(w, &showing, &labeled, &ticks);
  862.   if (showing) {
  863.     GetNiceRange(&low, &density, &ticks);
  864.     IViewSetYaxis(w, showing, labeled, ticks);
  865.   }
  866.   IViewSetRange(w, y, 0.0, density);
  867. }
  868.